package com.fount4j.generator.introspect;

import com.fount4j.generator.config.EntityConfig;
import com.fount4j.generator.context.GeneratorContext;
import com.fount4j.generator.info.ColumnInfo;
import com.fount4j.generator.info.EntityInfo;
import com.fount4j.generator.util.GeneratorFileUtils;
import com.google.common.base.CaseFormat;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * 实体类解析器
 *
 * @author Morven 2016/12/22
 */
public class EntityIntrospector implements BaseIntrospector {
    /**
     * 解析实体类信息
     *
     * @param context 生成器上下文
     */
    @Override
    public void introspect(GeneratorContext context) {
        context.setEntityInfo(new EntityInfo());
        introspectName(context);
        introspectPackage(context);
        introspectImports(context);
        introspectFile(context);
    }

    /**
     * 解析实体类文件路径
     *
     * @param context 生成器上下文
     */
    protected void introspectFile(GeneratorContext context) {
        EntityConfig entityConfig = context.getEntityConfig();
        String packageName = context.getTableConfig().getEntityPackage();
        if (StringUtils.isBlank(packageName)) {
            packageName = entityConfig.getPackageName();
        }

        File file = GeneratorFileUtils
                .getFile(entityConfig.getResourcePath(), packageName, context.getEntityInfo().getName() + ".java");
        context.getEntityInfo().setFile(file);
        context.getEntityInfo().setCustomContent(GeneratorFileUtils.getCustomContent(file));
    }

    /**
     * 解析实体类的类名
     *
     * @param context 生成器上下文
     */
    protected void introspectName(GeneratorContext context) {
        String name = context.getTableConfig().getEntityName();
        if (StringUtils.isBlank(name)) {
            String tableName = context.getTableInfo().getRealName();
            String ignoreTablePrefix = context.getEntityConfig().getIgnoreTablePrefix();
            if (StringUtils.isNotBlank(ignoreTablePrefix)) {
                String[] split = ignoreTablePrefix.split(",");
                for (String pre : split) {
                    String prefix = pre.trim();
                    if (tableName.startsWith(prefix)) {
                        tableName = tableName.replaceFirst(prefix, "");
                        break;
                    }
                }
            }
            name = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toUpperCase());
        }
        context.getEntityInfo().setName(name);
    }

    /**
     * 解析表
     *
     * @param context 生成器上下文
     */
    protected void introspectPackage(GeneratorContext context) {
        String packageContent = context.getTableConfig().getEntityPackage();
        if (StringUtils.isBlank(packageContent)) {
            packageContent = context.getEntityConfig().getPackageName();
        }

        String reference = context.getEntityInfo().getName();
        if (StringUtils.isBlank(packageContent)) {
            packageContent = "";
        } else {
            reference = packageContent + "." + reference;
            packageContent = "package " + packageContent + ";";
        }

        context.getEntityInfo().setPackageContent(packageContent);
        context.getEntityInfo().setReference(reference);
    }

    /**
     * 解析实体类需要导入的类
     *
     * @param context 生成器上下文
     */
    protected void introspectImports(GeneratorContext context) {
        List<ColumnInfo> columns = context.getTableInfo().getColumns();
        Set<String> imports = new LinkedHashSet<>();
        for (ColumnInfo column : columns) {
            Class<?> javaType = column.getJavaType();
            if (byte[].class.equals(javaType)) {
                continue;
            }
            String imp = javaType.getName();
            if (imp.startsWith("java.lang.")) {
                continue;
            }
            imports.add(imp);
        }
        List<String> importList = new ArrayList<>(imports);
        context.getEntityInfo().setImports(importList);
    }
}
